/* Copyright (c) 2022-2022, LiWangQian<liwangqian@huawei.com> All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef LIBCFGM_RULES_H
#define LIBCFGM_RULES_H

#include "libcfgm/types.h"
#include "libcfgm/error.h"
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct cfgm_rule {
    /**
     * 节点参数名称，用于匹配规则，如果为空指针，表示全匹配
     **/
    const char *name;

    /* 节点参数的数据类型 */
    cfgm_datatype_t type;

    /**
     * 参数值解析处理回调函数，开始新参数节点的解析，
     * 用于结构体、数组的成员解析前置处理
     * @param type 节点数据类型
     * @param context 解析规则的上下文指针
     * @return 返回该节点下子节点的解析规则
     */
    const struct cfgm_rule *(*begin)(cfgm_datatype_t type, void *context);

    /**
     * 参数值解析处理回调函数，节点数据值处理
     * @param type 节点类型
     * @param name 参数名称
     * @param len 节点参数数据类型的字节大小
     * @param value 节点参数数据指针，指向节点数据类型的指针
     * @param context 解析规则的上下文指针
     * @return 如果该值被接纳，则返回CFGM_OK，否则返回CFGM_EPARAM
     */
    int (*named_value)(cfgm_datatype_t type, const char *name,
        int len, const void *value, void *context);

    /**
     * 参数值解析处理回调函数，节点数据值处理
     * @param type 节点类型
     * @param index 参数索引
     * @param len 节点参数数据类型的字节大小
     * @param value 节点参数数据指针，指向节点数据类型的指针
     * @param context 解析规则的上下文指针
     * @return 如果该值被接纳，则返回CFGM_OK，否则返回CFGM_EPARAM
     */
    int (*indexed_value)(cfgm_datatype_t type, int index,
        int len, const void *value, void *context);

    /**
     * 参数值解析处理回调函数，结束参数节点的解析
     * @param type 节点数据类型
     * @param context 解析规则的上下文指针
     */
    void (*end)(cfgm_datatype_t type, void *context);

    /* 解析规则上下文指针，传递给回调函数 */
    void *context;
} cfgm_rule_t;

static inline const cfgm_rule_t *cfgm_rule_begin(
    cfgm_rule_t *rule, cfgm_datatype_t type, void *context)
{
    return rule ? rule->begin(type, context) : NULL;
}

static inline int cfgm_rule_named_value(
    cfgm_rule_t *rule, cfgm_datatype_t type, const char *name,
    int len, const void *value, void *context)
{
    return rule ? rule->named_value(type, name, len, value, context) : CFGM_ERULE;
}

static inline int cfgm_rule_indexed_value(
    cfgm_rule_t *rule, cfgm_datatype_t type, int index,
    int len, const void *value, void *context)
{
    return rule ? rule->indexed_value(type, index, len, value, context) : CFGM_ERULE;
}

static inline void cfgm_rule_end(
    cfgm_rule_t *rule, cfgm_datatype_t type, void *context)
{
    (rule ? rule->end(type, context) : (void)0);
}

typedef struct cfgm_rules_set {
    const cfgm_rule_t *rules;
    unsigned int count;
} cfgm_rules_set_t;


#ifdef __cplusplus
}
#endif

#endif /* LIBCFGM_RULES_H */
